
#include "./objects.hpp"

#include "./materials.hpp"
#include "./meshs.hpp"

namespace qbe::render {

LineMeshNode::LineMeshNode() {}
LineMeshNode::~LineMeshNode() {};
LineMeshNode::LineMeshNode(vsg::ref_ptr<vsg::Options> _options, Mesh2D _mesh, LineShaderMaterial2D _material, VkPrimitiveTopology _primitiveTopology)
    : options(_options), mesh(_mesh), material(_material), primitiveTopology(_primitiveTopology) {

  uniform = vsg::Value<LineUniform>::create();
  uniform->properties.dataVariance = vsg::DYNAMIC_DATA;
  updateUniform();

  addPipe();
  if (mesh.vertices->size() != 0)
    addCommands();
}

void LineMeshNode::addPipe() {
  auto vertexShader = vsg::ShaderStage::read(VK_SHADER_STAGE_VERTEX_BIT, "main", vsg::findFile(material.vertexShader, options));
  auto fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", vsg::findFile(material.fragmentShader, options));
  if (!vertexShader || !fragmentShader) {
    SPDLOG_INFO("Could not create shaders.");
    // return;
  }

  // Uniform绑定
  vsg::DescriptorSetLayoutBindings descriptorBindings{
      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT, nullptr},  // ClipSettings uniform
  };

  auto descriptorSetLayout = vsg::DescriptorSetLayout::create(descriptorBindings);

  // projection, view, and model matrices, actual push constant calls automatically provided by the VSG's RecordTraversal
  vsg::PushConstantRanges pushConstantRanges{{VK_SHADER_STAGE_VERTEX_BIT, 0, 128}};

  vsg::VertexInputState::Bindings vertexBindingsDescriptions = vsg::VertexInputState::Bindings{
      VkVertexInputBindingDescription{0, sizeof(vsg::vec2), VK_VERTEX_INPUT_RATE_VERTEX},  // vertex data
  };
  vsg::VertexInputState::Attributes vertexAttributeDescriptions = vsg::VertexInputState::Attributes{
      VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0},  // vertex data
  };

  if (instance) {
    vertexBindingsDescriptions = vsg::VertexInputState::Bindings{
        VkVertexInputBindingDescription{0, sizeof(vsg::vec2), VK_VERTEX_INPUT_RATE_VERTEX},    // vertex data
        VkVertexInputBindingDescription{1, sizeof(vsg::vec3), VK_VERTEX_INPUT_RATE_INSTANCE},  // instance tran
        VkVertexInputBindingDescription{2, sizeof(vsg::vec3), VK_VERTEX_INPUT_RATE_INSTANCE},  // instance mxr
        VkVertexInputBindingDescription{3, sizeof(vsg::vec3), VK_VERTEX_INPUT_RATE_INSTANCE},  // instance mxr
    };
    vertexAttributeDescriptions = vsg::VertexInputState::Attributes{
        VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0},  // vertex data
        VkVertexInputAttributeDescription{1, 1, VK_FORMAT_R32G32B32_SFLOAT, 0},  // instance tran
        VkVertexInputAttributeDescription{2, 2, VK_FORMAT_R32G32B32_SFLOAT, 0},  // instance mxr
        VkVertexInputAttributeDescription{3, 3, VK_FORMAT_R32G32B32_SFLOAT, 0},  // instance mxr
    };
  }

  VkBool32 primitiveRestart = VK_TRUE;
  vsg::GraphicsPipelineStates pipelineStates{vsg::VertexInputState::create(vertexBindingsDescriptions, vertexAttributeDescriptions),
                                             vsg::InputAssemblyState::create(primitiveTopology, primitiveRestart),
                                             vsg::RasterizationState::create(),
                                             vsg::MultisampleState::create(),
                                             vsg::ColorBlendState::create(),
                                             vsg::DepthStencilState::create()};

  auto pipelineLayout = vsg::PipelineLayout::create(vsg::DescriptorSetLayouts{descriptorSetLayout}, pushConstantRanges);
  auto graphicsPipeline = vsg::GraphicsPipeline::create(pipelineLayout, vsg::ShaderStages{vertexShader, fragmentShader}, pipelineStates);
  auto bindGraphicsPipeline = vsg::BindGraphicsPipeline::create(graphicsPipeline);

  // create UniformValue and associated DescriptorSets and binding
  auto uniformBuffer = vsg::DescriptorBuffer::create(uniform, 0);
  auto descriptorSet = vsg::DescriptorSet::create(descriptorSetLayout, vsg::Descriptors{uniformBuffer});
  auto bindDescriptorSet = vsg::BindDescriptorSet::create(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, descriptorSet);

  this->add(bindGraphicsPipeline);
  this->add(bindDescriptorSet);
};

void LineMeshNode::clear() {
  this->children.clear();
}

void LineMeshNode::addCommands() {
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mesh.vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(mesh.indices));
  drawCommands->addChild(vsg::DrawIndexed::create(mesh.indices->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

void LineMeshNode::update() {
  this->children.clear();
  addCommands();
}

void LineMeshNode::addMesh(const Mesh2D& mh) {
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
  drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

void LineMeshNode::addMeshs(const std::vector<Mesh2D>& meshs) {
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

void LineMeshNode::updateUniform() {
  uniform->value().color = material.uniform.color;
  uniform->value().isDash = material.uniform.isDash;
  uniform->value().canvas = material.uniform.canvas;
  uniform->value().dash = material.uniform.dash;
  uniform->value().gap = material.uniform.gap;
  uniform->dirty();
}

InstanceLineMeshNode::InstanceLineMeshNode(vsg::ref_ptr<vsg::Options> _options, Mesh2D _mesh, LineShaderMaterial2D _material,
                                           VkPrimitiveTopology _primitiveTopology) {
  options = _options;
  mesh = _mesh;
  material = _material;
  primitiveTopology = _primitiveTopology;
  instance = true;

  uniform = vsg::Value<LineUniform>::create();
  uniform->value().color = material.uniform.color;
  uniform->value().isDash = material.uniform.isDash;
  uniform->value().canvas = material.uniform.canvas;
  uniform->value().dash = material.uniform.dash;
  uniform->value().gap = material.uniform.gap;
  uniform->properties.dataVariance = vsg::DYNAMIC_DATA;

  addPipe();
  addCommands();
}

void InstanceLineMeshNode::addInstanceCmd(std::vector<Mesh2D>& meshs, uint32_t instance_count, vsg::ref_ptr<vsg::vec3Array> instance_v1,
                                          vsg::ref_ptr<vsg::vec3Array> instance_v2, vsg::ref_ptr<vsg::vec3Array> instance_v3) {
  for (auto& mh : meshs) {
    auto drawCommands = vsg::Commands::create();
    drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices, instance_v1, instance_v2, instance_v3}));
    drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
    drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), instance_count, 0, 0, 0));
    this->addChild(drawCommands);
  }
}

void InstanceLineMeshNode::addInstance(std::vector<Mesh2D>& meshs, InstanceMesh2D& instance_mesh) {
  for (auto& mh : meshs) {
    auto drawCommands = vsg::Commands::create();
    drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices, instance_mesh.m1, instance_mesh.m2, instance_mesh.m3}));
    drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
    drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), instance_mesh.count, 0, 0, 0));
    this->addChild(drawCommands);
  }
}
void InstanceLineMeshNode::updateInstance(std::vector<Mesh2D>& meshs, InstanceMesh2D& instance_mesh) {
  this->children.clear();
  addInstance(meshs, instance_mesh);
}

void InstanceLineMeshNode::updateInstance(std::vector<Mesh2D>& meshs, uint32_t instance_count, vsg::ref_ptr<vsg::vec3Array> instance_v1,
                                          vsg::ref_ptr<vsg::vec3Array> instance_v2, vsg::ref_ptr<vsg::vec3Array> instance_v3) {
  this->children.clear();
  for (auto& mh : meshs) {
    auto drawCommands = vsg::Commands::create();
    drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices, instance_v1, instance_v2, instance_v3}));
    drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
    drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), instance_count, 0, 0, 0));
    this->addChild(drawCommands);
  }
}

FillMeshNode::FillMeshNode() {}
FillMeshNode::~FillMeshNode() {};
FillMeshNode::FillMeshNode(vsg::ref_ptr<vsg::Options> _options, Mesh2D _mesh, FillShaderMaterial2D _material, VkPrimitiveTopology _primitiveTopology)
    : options(_options), mesh(_mesh), material(_material), primitiveTopology(_primitiveTopology) {
  uniform = vsg::Value<FillUniform>::create();
  uniform->properties.dataVariance = vsg::DYNAMIC_DATA;
  updateUniform();

  addPipe();
  if (mesh.vertices->size() != 0)
    addMesh(mesh);
}

void FillMeshNode::addPipe() {
  auto vertexShader = vsg::ShaderStage::read(VK_SHADER_STAGE_VERTEX_BIT, "main", vsg::findFile(material.vertexShader, options));
  auto fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", vsg::findFile(material.fragmentShader, options));
  if (!vertexShader || !fragmentShader) {
    SPDLOG_INFO("Could not create shaders.");
    // return;
  }

  // Uniform绑定
  vsg::DescriptorSetLayoutBindings descriptorBindings{
      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT, nullptr},  // ClipSettings uniform
  };

  auto descriptorSetLayout = vsg::DescriptorSetLayout::create(descriptorBindings);

  // projection, view, and model matrices, actual push constant calls automatically provided by the VSG's RecordTraversal
  vsg::PushConstantRanges pushConstantRanges{{VK_SHADER_STAGE_VERTEX_BIT, 0, 128}};

  vsg::VertexInputState::Bindings vertexBindingsDescriptions = vsg::VertexInputState::Bindings{
      VkVertexInputBindingDescription{0, sizeof(vsg::vec2), VK_VERTEX_INPUT_RATE_VERTEX},  // vertex data
  };
  vsg::VertexInputState::Attributes vertexAttributeDescriptions = vsg::VertexInputState::Attributes{
      VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0},  // vertex data
  };

  auto color_blend = vsg::ColorBlendState::create();
  color_blend->logicOpEnable = true;
  color_blend->logicOp = VK_LOGIC_OP_OR;
  VkBool32 primitiveRestart = VK_TRUE;
  vsg::GraphicsPipelineStates pipelineStates{vsg::VertexInputState::create(vertexBindingsDescriptions, vertexAttributeDescriptions),
                                             vsg::InputAssemblyState::create(primitiveTopology, primitiveRestart), vsg::RasterizationState::create(),
                                             vsg::MultisampleState::create(), color_blend,
                                             //  vsg::ColorBlendState::create(),
                                             vsg::DepthStencilState::create()};

  auto pipelineLayout = vsg::PipelineLayout::create(vsg::DescriptorSetLayouts{descriptorSetLayout}, pushConstantRanges);
  auto graphicsPipeline = vsg::GraphicsPipeline::create(pipelineLayout, vsg::ShaderStages{vertexShader, fragmentShader}, pipelineStates);
  auto bindGraphicsPipeline = vsg::BindGraphicsPipeline::create(graphicsPipeline);

  // create UniformValue and associated DescriptorSets and binding
  auto uniformBuffer = vsg::DescriptorBuffer::create(uniform, 0);
  auto descriptorSet = vsg::DescriptorSet::create(descriptorSetLayout, vsg::Descriptors{uniformBuffer});
  auto bindDescriptorSet = vsg::BindDescriptorSet::create(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, descriptorSet);

  this->add(bindGraphicsPipeline);
  this->add(bindDescriptorSet);
};

void FillMeshNode::updateUniform() {
  uniform->value().useTexture = material.uniform.useTexture;
  uniform->value().color = material.uniform.color;
  uniform->value().width = material.uniform.width;
  uniform->value().space = material.uniform.space;
  uniform->value().line_width = material.uniform.line_width;
  uniform->value().dot = material.uniform.dot;
  uniform->value().angle = material.uniform.angle;
  uniform->value().scale = material.uniform.scale;
  uniform->value().only_side = material.uniform.only_side;
  uniform->value().use_point_grid = material.uniform.use_point_grid;
  uniform->value().use_overlapping_discoloration = material.uniform.use_overlapping_discoloration;
  uniform->dirty();
}

void FillMeshNode::clear() {
  this->children.clear();
}

void FillMeshNode::addMesh(const Mesh2D& mh) {
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(mh.triangle_indices));
  drawCommands->addChild(vsg::DrawIndexed::create(mh.triangle_indices->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

void FillMeshNode::addMeshs(const std::vector<Mesh2D>& meshs) {
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

// MeshNodeNew::MeshNodeNew(vsg::ref_ptr<vsg::Options> _options, Mesh2D& _mesh, BorderMaterial& _material, VkPrimitiveTopology _primitiveTopology)
//     : options(_options), mesh(_mesh), material(_material), primitiveTopology(_primitiveTopology) {
//   auto uniform = vsg::Value<BorderUniform>::create();
//   uniform->value().color = _material.ubo.color;
//   uniform->value().canvas = _material.ubo.canvas;
//   uniform->value().dash = _material.ubo.dash;
//   uniform->value().gap = _material.ubo.gap;
//   uniform->value().isDash = _material.ubo.isDash;
//   uniform->properties.dataVariance = vsg::DYNAMIC_DATA;
//   addPipe(_options, _material.vert_path, _material.frag_path, uniform, _primitiveTopology, false);
//   addMesh(_mesh);
// }

// void MeshNodeNew::addMesh(const Mesh2D& mh) {
//   auto drawCommands = vsg::Commands::create();
//   drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices}));
//   drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
//   drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), 1, 0, 0, 0));
//   this->addChild(drawCommands);
// }

// void MeshNodeNew::clear() {
//   this->children.clear();
// }

// void MeshNodeNew::addMeshs(const std::vector<Mesh2D>& meshs) {
//   for (auto& mh : meshs) {
//     addMesh(mh);
//   }
// }

// void MeshNodeNew::updateMesh(const Mesh2D& mh) {
//   this->children.clear();
//   addMesh(mh);
// }

// void MeshNodeNew::updateMeshs(const std::vector<Mesh2D>& meshs) {
//   this->children.clear();
//   for (auto& mh : meshs) {
//     addMesh(mh);
//   }
// }

MeshNode::MeshNode(vsg::ref_ptr<vsg::Options> _options, Mesh2D _mesh, ShaderMaterial2D _material, VkPrimitiveTopology _primitiveTopology,
                   bool _instance)
    : options(_options), mesh(_mesh), material(_material), primitiveTopology(_primitiveTopology), instance(_instance) {
  addPipe();
  addCommands();
}

void MeshNode::addPipe() {
  auto vertexShader = vsg::ShaderStage::read(VK_SHADER_STAGE_VERTEX_BIT, "main", vsg::findFile(material.vertexShader, options));
  auto fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", vsg::findFile(material.fragmentShader, options));
  if (!vertexShader || !fragmentShader) {
    SPDLOG_INFO("Could not create shaders.");
    // return;
  }

  // Uniform绑定
  vsg::DescriptorSetLayoutBindings descriptorBindings{
      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT, nullptr},  // ClipSettings uniform
      // { binding, descriptorType, descriptorCount, stageFlags, pImmutableSamplers}
  };

  auto descriptorSetLayout = vsg::DescriptorSetLayout::create(descriptorBindings);

  // projection, view, and model matrices, actual push constant calls automatically provided by the VSG's RecordTraversal
  vsg::PushConstantRanges pushConstantRanges{{VK_SHADER_STAGE_VERTEX_BIT, 0, 128}};

  vsg::VertexInputState::Bindings vertexBindingsDescriptions = vsg::VertexInputState::Bindings{
      VkVertexInputBindingDescription{0, sizeof(vsg::vec2), VK_VERTEX_INPUT_RATE_VERTEX},  // vertex data
  };
  vsg::VertexInputState::Attributes vertexAttributeDescriptions = vsg::VertexInputState::Attributes{
      VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0},  // vertex data
  };

  if (instance) {
    vertexBindingsDescriptions = vsg::VertexInputState::Bindings{
        VkVertexInputBindingDescription{0, sizeof(vsg::vec2), VK_VERTEX_INPUT_RATE_VERTEX},    // vertex data
        VkVertexInputBindingDescription{1, sizeof(vsg::vec3), VK_VERTEX_INPUT_RATE_INSTANCE},  // instance tran
        VkVertexInputBindingDescription{2, sizeof(vsg::vec3), VK_VERTEX_INPUT_RATE_INSTANCE},  // instance mxr
        VkVertexInputBindingDescription{3, sizeof(vsg::vec3), VK_VERTEX_INPUT_RATE_INSTANCE},  // instance mxr
    };
    vertexAttributeDescriptions = vsg::VertexInputState::Attributes{
        VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0},  // vertex data
        VkVertexInputAttributeDescription{1, 1, VK_FORMAT_R32G32B32_SFLOAT, 0},  // instance tran
        VkVertexInputAttributeDescription{2, 2, VK_FORMAT_R32G32B32_SFLOAT, 0},  // instance mxr
        VkVertexInputAttributeDescription{3, 3, VK_FORMAT_R32G32B32_SFLOAT, 0},  // instance mxr
    };
  }

  // primitiveTopology = VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
  // primitiveTopology = VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;

  // 图元重启默认开启
  VkBool32 primitiveRestart = VK_TRUE;

  vsg::GraphicsPipelineStates pipelineStates{vsg::VertexInputState::create(vertexBindingsDescriptions, vertexAttributeDescriptions),
                                             vsg::InputAssemblyState::create(primitiveTopology, primitiveRestart),
                                             vsg::RasterizationState::create(),
                                             vsg::MultisampleState::create(),
                                             vsg::ColorBlendState::create(),
                                             vsg::DepthStencilState::create()};

  auto pipelineLayout = vsg::PipelineLayout::create(vsg::DescriptorSetLayouts{descriptorSetLayout}, pushConstantRanges);
  auto graphicsPipeline = vsg::GraphicsPipeline::create(pipelineLayout, vsg::ShaderStages{vertexShader, fragmentShader}, pipelineStates);
  auto bindGraphicsPipeline = vsg::BindGraphicsPipeline::create(graphicsPipeline);

  // create UniformValue and associated DescriptorSets and binding
  auto uniform = vsg::Value<render::Uniform>::create();
  uniform->value().line_color = material.uniform.line_color;
  uniform->value().fill_color = material.uniform.fill_color;
  uniform->properties.dataVariance = vsg::DYNAMIC_DATA;

  auto uniformBuffer = vsg::DescriptorBuffer::create(uniform, 0);
  auto descriptorSet = vsg::DescriptorSet::create(descriptorSetLayout, vsg::Descriptors{uniformBuffer});
  auto bindDescriptorSet = vsg::BindDescriptorSet::create(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, descriptorSet);

  // create StateGroup as the root of the scene/command graph to hold the GraphicsPipeline, and binding of Descriptors to decorate the whole graph
  // auto this= vsg::StateGroup::create();
  this->add(bindGraphicsPipeline);
  this->add(bindDescriptorSet);
};

void MeshNode::clear() {
  this->children.clear();
}

void MeshNode::addCommands() {
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mesh.vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(mesh.indices));
  drawCommands->addChild(vsg::DrawIndexed::create(mesh.indices->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

void MeshNode::addMesh(const Mesh2D& mh) {
  auto drawCommands = vsg::Commands::create();
  drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices}));
  drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
  drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), 1, 0, 0, 0));
  this->addChild(drawCommands);
}

void MeshNode::update() {
  this->children.clear();
  addCommands();
}

void MeshNode::addCmd(const std::vector<Mesh2D>& meshs) {
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

void MeshNode::addMeshs(const std::vector<Mesh2D>& meshs) {
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

void MeshNode::updateMesh(const Mesh2D& mh) {
  this->children.clear();
  addMesh(mh);
}

void MeshNode::updateMeshs(const std::vector<Mesh2D>& meshs) {
  this->children.clear();
  for (auto& mh : meshs) {
    addMesh(mh);
  }
}

InstanceMeshNode::InstanceMeshNode(vsg::ref_ptr<vsg::Options> _options, Mesh2D _mesh, ShaderMaterial2D _material,
                                   VkPrimitiveTopology _primitiveTopology) {
  options = _options;
  mesh = _mesh;
  material = _material;
  primitiveTopology = _primitiveTopology;
  instance = true;

  addPipe();
  addCommands();
}

void InstanceMeshNode::addInstanceCmd(std::vector<Mesh2D>& meshs, uint32_t instance_count, vsg::ref_ptr<vsg::vec3Array> instance_v1,
                                      vsg::ref_ptr<vsg::vec3Array> instance_v2, vsg::ref_ptr<vsg::vec3Array> instance_v3) {
  for (auto& mh : meshs) {
    auto drawCommands = vsg::Commands::create();
    drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices, instance_v1, instance_v2, instance_v3}));
    drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
    drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), instance_count, 0, 0, 0));
    this->addChild(drawCommands);
  }
}

void InstanceMeshNode::addInstance(std::vector<Mesh2D>& meshs, InstanceMesh2D& instance_mesh) {
  for (auto& mh : meshs) {
    auto drawCommands = vsg::Commands::create();
    drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices, instance_mesh.m1, instance_mesh.m2, instance_mesh.m3}));
    drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
    drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), instance_mesh.count, 0, 0, 0));
    this->addChild(drawCommands);
  }
}
void InstanceMeshNode::updateInstance(std::vector<Mesh2D>& meshs, InstanceMesh2D& instance_mesh) {
  this->children.clear();
  addInstance(meshs, instance_mesh);
}

void InstanceMeshNode::updateInstance(std::vector<Mesh2D>& meshs, uint32_t instance_count, vsg::ref_ptr<vsg::vec3Array> instance_v1,
                                      vsg::ref_ptr<vsg::vec3Array> instance_v2, vsg::ref_ptr<vsg::vec3Array> instance_v3) {
  this->children.clear();
  for (auto& mh : meshs) {
    auto drawCommands = vsg::Commands::create();
    drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{mh.vertices, instance_v1, instance_v2, instance_v3}));
    drawCommands->addChild(vsg::BindIndexBuffer::create(mh.indices));
    drawCommands->addChild(vsg::DrawIndexed::create(mh.indices->size(), instance_count, 0, 0, 0));
    this->addChild(drawCommands);
  }
}

}  // namespace qbe::render